
import java.io.*;
import java.net.*;
import java.security.Provider;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import nanoxml.XMLElement;

/**
 *
 * @author marduke
 * basado en: http://zerioh.tripod.com/ressources/sockets.html
 */
public class Servidor {

    static int DEFAULT = 1800;
    ServerSocket providerSocket;
    Socket connection = null;
    ObjectOutputStream out;
    ObjectInputStream in;
    String message;
    int puerto = 2004;
    Vector<String> vecinos = new Vector();
    Vector<String> archivos = new Vector();
    String dirArchivos;
    String ArchivoTraza = "log";
    //BufferedWriter traza;

    Servidor() {
    }

    Servidor(int puerto, Vector vecinos, Vector archivos, String dirArchivos, String archivoTraza) {
        this.puerto = puerto;
        this.vecinos = vecinos;
        this.archivos = archivos;
        this.dirArchivos = dirArchivos;
        this.ArchivoTraza = archivoTraza;
    }

    void imprimirTraza(String message) {


        try {
            // Create file
            FileWriter fstream = new FileWriter(ArchivoTraza,true);
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(message + "\n");

            out.close();
        } catch (Exception e) {//Catch exception if any
            System.err.println("Error: Error el imprimir en el archivo traza\n" );
        }

    }
    void run() throws Exception {
        try {

//            FileWriter fstream = new FileWriter(ArchivoTraza, true);
//            System.out.println(ArchivoTraza);
//            traza = new BufferedWriter(fstream);

            //1. Creando el servidor del socket
            providerSocket = new ServerSocket(puerto, 10);
            //2. Wait for connection
            InetAddress serverAddr = InetAddress.getLocalHost();
            System.out.println("Esperenado por una conexion ");
            connection = providerSocket.accept();
            imprimirTraza("Se recibio una conexion desde " + connection.getInetAddress().getHostAddress());

            //3. Consigo los input y output stream
            out = new ObjectOutputStream(connection.getOutputStream());
            out.flush();
            in = new ObjectInputStream(connection.getInputStream());
            sendMessage("Conexion Realizada con exito");
            //4. La parte del protocolo del servidor
            do {
                try {
                    message = (String) in.readObject();

                    imprimirTraza("Se recibio el siguiente mensaje del cliente: " + message);
                    Scanner sc = new Scanner(message);

                    if (sc.hasNext()) {
                        String tmp = sc.next();

                        if (tmp.compareTo("Consulta") == 0) {
                            String arg1 = sc.next();
                            String arg2 = sc.nextLine();

                            XMLElement xml = new XMLElement();
                            xml.setName("consulta");

                            XMLElement visitados = new XMLElement();
                            visitados.setName("visitados");

                            InetAddress addr = InetAddress.getLocalHost();

                            imprimirTraza("El mensaje del cliente se trataba de una consutlta");

                            ClienteNodo cliente = new ClienteNodo("Consulta "
                                    + arg1 + " " + arg2 + "%-XCTW-%" + xml.toString()
                                    + "%-XCTW-%" + visitados.toString(),
                                    addr.getHostAddress());

                            String laconsulta = cliente.run();
                            String tmp2[] = laconsulta.split("%-XCTW-%");

                            imprimirTraza("Se recibio el siguiente mensaje de la consulta: " + tmp2[0] + "\n");
                            
                            sendMessage(tmp2[0]);

                            imprimirTraza("Se mando al cliente: " + tmp2[0]);

                            //deberia leer los demas parametros y mandarlo a la funcion consulta
                            //consulta(dirArchivos, arg1, arg2);

                            //System.out.println("server> La consulta fue: "
                            //      +tmp2[0]);


                        } else if (tmp.compareTo("Solicitud") == 0) {

                            //deberia leer los demas parametros y mandarlos a la
                            //funcion consulta

                            imprimirTraza("Es una solicitud de archivo");
                            String arg1 = sc.next();
                            String arg2 = sc.next();
                            //System.out.println("server> Es una Solicitud");
                            //System.out.println(arg1+"\n");
                            //System.out.println(arg2+"\n");
                            solicitud(arg1, arg2);
//                            sendMessage("Descargado");

                        } else if (tmp.compareTo("Alcanzables") == 0) {
                            //deberia mandarlo a la funcion alcanzable
                            // alcanzable(vecinos);

                            imprimirTraza("Es la operacion alcanzable");
                            XMLElement visitados = new XMLElement();
                            visitados.setName("visitados");


                            InetAddress addr = InetAddress.getLocalHost();
                            ClienteNodo cliente = new ClienteNodo("Alcanzable "
                                    + visitados.toString(), addr.getHostName());
                            String Alcanzables = cliente.run();
                            //System.out.println("server> Es alcanzables");

                            sendMessage(Alcanzables);
                            imprimirTraza("Se mando el siguiente mensaje al cliente: " + Alcanzables);
                        } else if (message.equals("bye")) {
                            imprimirTraza("Se cerro la conexion");
                            sendMessage("bye");
                        } else {
                            //System.out.println("server> Ahi un error en el " +
                            //      "protocolo");
                            imprimirTraza("Error en el protocolo");
                            sendMessage("bye");
                        }
                    }
                } catch (ClassNotFoundException classnot) {
                    System.err.println("Data received in unknown format");
                }
            } while (!message.equals("bye"));
        } catch (BindException bindExc) {
            System.err.println("Ya existe un programa corriende en ese puerto.");
            System.exit(4);

        } catch (IOException ioException) {
            ioException.printStackTrace();
        } finally {
            //4: Closing connection
            try {
                in.close();
                out.close();
                //traza.close();
                providerSocket.close();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }

        }

    }

    void sendMessage(String msg) {
        try {
            out.writeObject(msg);
            out.flush();
            //System.out.println("server>" + msg);
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }

    }

    void solicitud(String archivo, String maquina) {
        InetAddress addr;
        try {
            addr = InetAddress.getLocalHost();
            ClienteNodo archivoFoto = new ClienteNodo("Solicitud " + archivo + " " + maquina, addr.getHostAddress());
            archivoFoto.run();
        } catch (UnknownHostException ex) {
        }

    }

    private void getIp() {
        try {
            InetAddress addr = providerSocket.getInetAddress();

            // Get IP Address
            byte[] ipAddr = addr.getAddress();
            String ipAdd = ipAddr[0] + "." + ipAddr[1] + "." + ipAddr[2] + "."
                    + ipAddr[3] + ".";

            System.out.println(ipAdd);

            // Get hostname
            String hostname = addr.getHostName();
            System.out.println(hostname);
        } catch (Exception e) {
        }
    }

    static String getTitulo(String FileXML) throws Exception {

        XMLElement xml = new XMLElement();
        boolean conseguido = false;
        String retorno = "No se consigio";
        FileReader reader = new FileReader(FileXML);
        xml.parseFromReader(reader);

        Enumeration children = xml.enumerateChildren();
        while (children.hasMoreElements()) {
            XMLElement child = (XMLElement) children.nextElement();
            if (child.getName().compareTo("titulo") == 0) {
                retorno = child.getContent();
            }

        }

        return retorno;
    }

    static String getClaves(String FileXML) throws Exception {

        XMLElement xml = new XMLElement();
        boolean conseguido = false;
        String retorno = "No se consiguio";
        FileReader reader = new FileReader(FileXML);
        xml.parseFromReader(reader);



        Enumeration children = xml.enumerateChildren();
        while (children.hasMoreElements()) {
            XMLElement child = (XMLElement) children.nextElement();
            if (child.getName().compareTo("titulo") == 0) {
                retorno = child.getContent();
            }

        }

        return retorno;
    }
}
